#include "../global.h"

class vtkTIPWCallback : public vtkCommand
{
public:
    static vtkTIPWCallback *New()
    {
        return new vtkTIPWCallback;
    }

    virtual void Execute(vtkObject *caller, unsigned long, void*)
    {
        vtkBoxWidget *boxWidget = reinterpret_cast<vtkBoxWidget*>(caller);
        boxWidget->GetPlanes(m_planes);
        m_vMapper->SetClippingPlanes(m_planes);
        m_volume->VisibilityOn();
    }

    void setParameter(vtkPlanes *p, vtkVolume *v, vtkVolumeRayCastMapper *m)
    {
        m_planes = p;
        m_volume = v;
        m_vMapper = m;
    }
protected:
    vtkTIPWCallback():m_planes(0),m_volume(0),m_vMapper(0){}
    vtkPlanes *m_planes;
    vtkVolume *m_volume;
    vtkVolumeRayCastMapper *m_vMapper;

};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkCreate(reader, vtkDICOMImageReader);
    reader->SetDataByteOrderToLittleEndian();
    reader->SetDirectoryName(path.toStdString().c_str());
    reader->Update();

    vtkCreate(imageCast, vtkImageCast);
    imageCast->SetInputConnection(reader->GetOutputPort());
    imageCast->SetOutputScalarTypeToUnsignedShort();
    imageCast->Update();

    vtkCreate(opacityTransferFunction, vtkPiecewiseFunction);
    opacityTransferFunction->AddPoint(20, 0.0);
    opacityTransferFunction->AddPoint(255.0, 0.22);

    vtkCreate(colorTransferFunction, vtkColorTransferFunction);
    colorTransferFunction->AddRGBPoint(0.0, 0.0, 0.5, 0.0);
    colorTransferFunction->AddRGBPoint(60.0, 1.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(128.0, 0.2, 0.1, 0.9);
    colorTransferFunction->AddRGBPoint(196.0, 0.27, 0.21, 0.1);
    colorTransferFunction->AddRGBPoint(255.0, 0.8, 0.8, 0.8);

    vtkCreate(volumeProperty, vtkVolumeProperty);
    volumeProperty->SetColor(colorTransferFunction);
    volumeProperty->SetScalarOpacity(opacityTransferFunction);
    volumeProperty->ShadeOn();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->SetAmbient(0.2);
    volumeProperty->SetDiffuse(0.9);
    volumeProperty->SetSpecular(0.2);
    volumeProperty->SetSpecularPower(10);

    vtkCreate(compositeFunction, vtkVolumeRayCastCompositeFunction);
    vtkCreate(gradest, vtkFiniteDifferenceGradientEstimator);
    vtkCreate(volumeMapper, vtkVolumeRayCastMapper);
    volumeMapper->SetVolumeRayCastFunction(compositeFunction);
    volumeMapper->SetGradientEstimator(gradest);
    volumeMapper->SetInputConnection(imageCast->GetOutputPort());
    volumeMapper->SetNumberOfThreads(3);

    vtkCreate(planes, vtkPlanes);
    vtkCreate(volume, vtkVolume);
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkCreate(renderer, vtkRenderer);
    vtkWidgetCreate(widget, QVTKWidget);
    QVTKWidget* vtkWidget = widget.data();
    vtkWidget->GetRenderWindow()->AddRenderer(renderer);

    vtkCreate(myCallback, vtkTIPWCallback);
    myCallback->setParameter(planes, volume, volumeMapper);

    vtkCreate(boxWidget, vtkBoxWidget);
    boxWidget->SetInteractor(vtkWidget->GetRenderWindow()->GetInteractor());
    boxWidget->SetPlaceFactor(1);
    boxWidget->GetOutlineProperty()->SetColor(1,1,1);
    boxWidget->GetHandleProperty()->SetColor(0,1,0);
    boxWidget->SetInputData(imageCast->GetOutput());
    boxWidget->PlaceWidget();
    boxWidget->InsideOutOn();
    boxWidget->AddObserver(vtkCommand::InteractionEvent, myCallback);
    boxWidget->On();

    vtkCreate(axesActor, vtkAnnotatedCubeActor);
    axesActor->SetXPlusFaceText("R");
    axesActor->SetXMinusFaceText("L");
    axesActor->SetYMinusFaceText("H");
    axesActor->SetYPlusFaceText("F");
    axesActor->SetZMinusFaceText("P");
    axesActor->SetZPlusFaceText("A");
    axesActor->GetTextEdgesProperty()->SetColor(1,1,0);
    axesActor->GetTextEdgesProperty()->SetLineWidth(1);
    axesActor->GetCubeProperty()->SetColor(0,0,1);

    vtkCreate(axesWidget, vtkOrientationMarkerWidget);
    axesWidget->SetOrientationMarker(axesActor);
    axesWidget->SetInteractor(vtkWidget->GetRenderWindow()->GetInteractor());
    axesWidget->EnabledOn();
    axesWidget->InteractiveOff();
    axesWidget->SetViewport(0.85, 0.85, 1, 1);
    renderer->ResetCamera();

    renderer->AddVolume(volume);
    renderer->SetBackground(0, 0, 0);
    vtkWidget->resize(WINDOW_WIDTH, WINDOW_HEIGHT);
    vtkWidget->show();

    return a.exec();
}
